Title: How to check if your smartcard's GPG key is in cache PART 3
Date: 2017-03-13 17:05
Category: gpg
Tags: gpg, unix, CLI, gpg-agent, awk, regex, smartcard


###GPG SmartCard Cache Checking
In previous posts I talked about checking if a gpg key was cached, and used a broad check with my awk to do so.
By 'broad', I just wish to point out that you *could* build the check around a specific key-grip if you cared to.
And recently I got around to ordering a 'traditional' smartcard from [kernel concepts].
While I've had and used a [yubikey neo] for a while with my laptop/phone, I have been utilizing an on laptop subkey for 'convenience'.
The local subkey was handling my `pass` ([password store]) datebase, and in the past my `cryptshotr` keyfile.


####Personal Desires
My reason for getting a classic style smartcard are as follows:

1. I have the card slot on my laptop.
2. I don't want to have a fullsized yubikey sticking out all the time.
3. I don't want to burn a USB port by always having a yubikey nano living in it.


###Hands on
After getting the card I trimmed the edge down so that it barely sticks out from the laptop.


####Multiple SmartCard Woes
To set up my new card, I pulled a copy of my non-stub laptop keys (encryption, signature, and authentication) out of secure storage, and ran a `export GNUPGHOME=...` to point at the copy.
Once my keys and configurations are finished on the new card and I was back to my normal keyring <sup>(temp dir having been shreaded)</sup>, I ran into an issue where it kept asking for the yubikey by serial...
Unfortunately running `gpg --card-edit` and `fetch` did not help.
To fix this I ran good old `gpg-connect-agent 'keyinfo --list' /bye 2>/dev/null` <sup>(from the previous posts: [Part1], [Part2])</sup> to identify the key-grips, and deleted the three offending `/.gnupg/private-keys-v1.d/KEY_GRIP_HERE.key` files.
After they were cleared out, I was successfully about to `gpg --card-edit` and `fetch` from the new key.


####Verifying Functionality
While testing that the keys on the smartcard worked, I also checked on my previous cache check solution.
Sadly I found that `gpg-connect-agent 'keyinfo --list' /bye 2>/dev/null` doesn't show the smartcard status.

While reading thought the output of `gpg-connect-agent 'help' /bye`, and each individual help page, I see `scd`.

    :::bash
    ~ -> gpg-connect-agent 'help scd' /bye
    # SCD <commands to pass to the scdaemon>
    #
    # This is a general quote command to redirect everything to the
    # SCdaemon.
    OK


####Alice Falling Down the Rabbit Hole
So now, here I am in my `bash` shell, sending commands to the `gpg-agent` shell, sending commands to the `scdaemon` shell.

    :::bash
    ~ -> gpg-connect-agent 'scd help' /bye
    # NOP
    # CANCEL
    # OPTION
    # BYE
    # AUTH
    # RESET
    # END
    # HELP
    # SERIALNO [--demand=<serialno>] [<apptype>]
    # LEARN [--force] [--keypairinfo]
    # READCERT <hexified_certid>|<keyid>
    # READKEY [--advanced] <keyid>
    # SETDATA [--append] <hexstring>
    # PKSIGN [--hash=[rmd160|sha{1,224,256,384,512}|md5]] <hexified_id>
    # PKAUTH <hexified_id>
    # PKDECRYPT <hexified_id>
    # INPUT
    # OUTPUT
    # GETATTR <name>
    # SETATTR <name> <value>
    # WRITECERT <hexified_certid>
    # WRITEKEY [--force] <keyid>
    # GENKEY [--force] [--timestamp=<isodate>] <no>
    # RANDOM <nbytes>
    # PASSWD [--reset] [--nullpin] <chvno>
    # CHECKPIN <idstr>
    # LOCK [--wait]
    # UNLOCK
    # GETINFO <what>
    # RESTART
    # DISCONNECT
    # APDU [--[dump-]atr] [--more] [--exlen[=N]] [hexstring]
    # KILLSCD
    OK

While reading through the help pages on each of these, `GETINFO` looks promising.

    :::bash
    ~ -> gpg-connect-agent 'scd help getinfo' /bye
    # GETINFO <what>
    #
    # Multi purpose command to return certain information.
    # Supported values of WHAT are:
    #
    # version     - Return the version of the program.
    # pid         - Return the process id of the server.
    #
    # socket_name - Return the name of the socket.
    #
    # status - Return the status of the current reader (in the future, may
    # also return the status of all readers).  The status is a list of
    # one-character flags.  The following flags are currently defined:
    #   'u'  Usable card present.  This is the normal state during operation.
    #   'r'  Card removed.  A reset is necessary.
    # These flags are exclusive.
    #
    # reader_list - Return a list of detected card readers.  Does
    #               currently only work with the internal CCID driver.
    #
    # deny_admin  - Returns OK if admin commands are not allowed or
    #               GPG_ERR_GENERAL if admin commands are allowed.
    #
    # app_list    - Return a list of supported applications.  One
    #               application per line, fields delimited by colons,
    #               first field is the name.
    #
    # card_list   - Return a list of serial numbers of active cards,
    #               using a status response.
    OK

Particularly, I noted `card_list` and its used of the word *'active'*.

Upon testing, I find that `gpg-connect-agent 'scd getinfo card_list' /bye` is a seemingly reliable way of seeing if a smartcard key is in cache.

If the card is inserted **AND** the card has been used to decrypt you get:

    :::bash
    ~ -> gpg-connect-agent 'scd getinfo card_list' /bye
    S SERIALNO REDACTEDREDACTEDREDACTEDREDACTED
    OK

If the card is removed, if `scdaemon` wasn't running, or if the card is inserted **AND** the card has not been used:

    :::bash
    ~ -> gpg-connect-agent 'scd getinfo card_list' /bye
    OK


###Implementing
The following is a tasty little piece of awk that check is any smartcard is listed as active, and returns '`1`' if yes.

    :::bash
    gpg-connect-agent 'scd getinfo card_list' /bye 2>/dev/null | awk 'BEGIN {CH=0} /SERIALNO/ {if($0!=""){CH=1}} END {print CH}'

And for a cherry on top, there is a *'oneliner'* that will check if either a local key or a smartcard is cached:

    :::bash
    { gpg-connect-agent 'keyinfo --list' /bye 2>/dev/null; gpg-connect-agent 'scd getinfo card_list' /bye 2>/dev/null; } | awk 'BEGIN{CH=0} /^S/ {if($7==1){CH=1}; if($2=="SERIALNO"){CH=1}} END{if($0!=""){print CH} else {print "none"}}'

###Bonus: Pictures of smartcards in a Thinkpad.
Because it is ***impossible*** to find a picture of a smartcard in a Thinkpad laptop on the internet, here is my x260 with a card in it.

* normal
![thinkpad_smartcard_full]({static}/pics/thinkpad_smartcard_full.jpg)
* trimmed
![thinkpad_smartcard_cut]({static}/pics/thinkpad_smartcard_cut.jpg)


###Links
[kernel concepts]  
[yubikey neo]  
[password store]  
[Part1]  
[Part2]  


[kernel concepts]: http://shop.kernelconcepts.de/
[yubikey neo]: https://www.yubico.com/products/yubikey-hardware/yubikey-neo/
[password store]: https://www.passwordstore.org/
[Part1]: {filename}007-gpg_cache_check.md
[Part2]: {filename}009-gpg_cache_check_part2.md
